package org.jsola.hr.service.impl;

import org.jsola.common.StrKit;
import org.jsola.core.Page;
import org.jsola.core.entity.BaseDO;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IEmpAdditionalFieldsDAO;
import org.jsola.hr.dto.EmpAdditionalFieldsAddDTO;
import org.jsola.hr.dto.EmpAdditionalFieldsUpdateDTO;
import org.jsola.hr.entity.EmpAdditionalFieldsDO;
import org.jsola.hr.query.EmpAdditionalFieldsQuery;
import org.jsola.hr.service.IEmpAdditionalFieldsService;
import org.jsola.hr.vo.EmpAdditionalFieldsListVO;
import org.jsola.hr.vo.EmpAdditionalFieldsVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 员工额外字段信息表
 *
 * @author zhr
 */
@Service("hrEmpAdditionalFieldsServiceImpl")
public class EmpAdditionalFieldsServiceImpl implements IEmpAdditionalFieldsService {

    @Autowired
    private IEmpAdditionalFieldsDAO empAdditionalFieldsDAO;

    /**
     * 员工
     */
    private static final Integer TYPE_EMP = 1;

    /**
     * 预登记
     */
    private static final Integer TYPE_CHECK_IN = 2;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public EmpAdditionalFieldsVO save(EmpAdditionalFieldsAddDTO empAdditionalFieldsAddDTO, TokenUser tokenUser) {
        if (StringUtils.isEmpty(empAdditionalFieldsAddDTO.getModuleCode())) {
            throw new ParamException("模块类型不能为空");
        }
        if (StringUtils.isEmpty(empAdditionalFieldsAddDTO.getEmpId())) {
            throw new ParamException("员工id不能为空");
        }
        // 转DO
        EmpAdditionalFieldsDO empAdditionalFieldsDO = empAdditionalFieldsAddDTO.to(EmpAdditionalFieldsDO.class);
        // 保存
        empAdditionalFieldsDO = save(empAdditionalFieldsDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return empAdditionalFieldsDO.to(EmpAdditionalFieldsVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(EmpAdditionalFieldsUpdateDTO empAdditionalFieldsUpdateDTO, TokenUser tokenUser) {
        //转DO
        EmpAdditionalFieldsDO empAdditionalFieldsDO = empAdditionalFieldsUpdateDTO.to(EmpAdditionalFieldsDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(empAdditionalFieldsDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, Long... empAdditionalFieldsIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) empAdditionalFieldsIds);
    }


    @Override
    public EmpAdditionalFieldsVO selectById(Long empAdditionalFieldsId, String siteId) {
        EmpAdditionalFieldsDO empAdditionalFieldsDO = selectDOById(empAdditionalFieldsId, siteId);
        if (empAdditionalFieldsDO == null) {
            return null;
        }
        return empAdditionalFieldsDO.to(EmpAdditionalFieldsVO.class);
    }

    @Override
    public List<EmpAdditionalFieldsListVO> select(EmpAdditionalFieldsQuery empAdditionalFieldsQuery, String siteId) {
        List<EmpAdditionalFieldsDO> empAdditionalFieldsDOList = selectDO(empAdditionalFieldsQuery, siteId);
        if (CollectionUtils.isEmpty(empAdditionalFieldsDOList)) {
            return empAdditionalFieldsDOList == null ? null : new ArrayList<>();
        }
        return empAdditionalFieldsDOList.stream()
                .map(empAdditionalFieldsDO -> empAdditionalFieldsDO.to(EmpAdditionalFieldsListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public List<EmpAdditionalFieldsDO> selectByFiledId(Long filedId) {
        Example example = new Example(EmpAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("fieldId", filedId);
        return empAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<EmpAdditionalFieldsDO> selectByFiledIds(List<Long> filedIds) {
        if (CollectionUtils.isEmpty(filedIds)) {
            return new ArrayList<>();
        }
        Example example = new Example(EmpAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andIn("fieldId", filedIds);
        return empAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<EmpAdditionalFieldsDO> selectByFiledIdsAndEmpId(List<Long> filedIds, String empId) {
        if (CollectionUtils.isEmpty(filedIds)) {
            return new ArrayList<>();
        }
        Example example = new Example(EmpAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("empId", empId)
                .andIn("fieldId", filedIds);
        return empAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public Map<String, List<EmpAdditionalFieldsDO>> selectByFiledIdsAndEmpIds(List<Long> filedIds, List<String> empIds) {
        if (CollectionUtils.isEmpty(filedIds) || CollectionUtils.isEmpty(empIds)) {
            return new HashMap<>();
        }
        Example example = new Example(EmpAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andIn("empId", empIds)
                .andIn("fieldId", filedIds);
        List<EmpAdditionalFieldsDO> empAdditionalFieldsDOS = empAdditionalFieldsDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(empAdditionalFieldsDOS)) {
            return new HashMap<>();
        }
        return empAdditionalFieldsDOS.parallelStream()
                .collect(Collectors.groupingBy(EmpAdditionalFieldsDO::getEmpId));
    }

    @Override
    public EmpAdditionalFieldsDO selectByFiledIdAndEmpId(Long filedId, String empId) {
        if (StrKit.isEmpty(empId)) {
            return null;
        }
        Example example = new Example(EmpAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("empId", empId)
                .andEqualTo("fieldId", filedId);
        return empAdditionalFieldsDAO.selectOneByExample(example);
    }

    @Override
    public int selectCount(EmpAdditionalFieldsQuery empAdditionalFieldsQuery, String siteId) {
        Example example = buildExample(empAdditionalFieldsQuery, siteId);
        return empAdditionalFieldsDAO.selectCountByExample(example);
    }

    @Override
    public Page<EmpAdditionalFieldsListVO> selectPage(EmpAdditionalFieldsQuery empAdditionalFieldsQuery, String siteId) {
        Example example = buildExample(empAdditionalFieldsQuery, siteId);
        Page<EmpAdditionalFieldsDO> page = empAdditionalFieldsDAO.selectPageByExample(example,
                empAdditionalFieldsQuery.getPageNo(),
                empAdditionalFieldsQuery.getPageSize());

        return page.to(EmpAdditionalFieldsListVO.class);
    }

    @Override
    public EmpAdditionalFieldsDO selectDOById(Long empAdditionalFieldsId, String siteId) {
        return listById(empAdditionalFieldsId, siteId);
    }

    @Override
    public List<EmpAdditionalFieldsDO> selectDO(EmpAdditionalFieldsQuery empAdditionalFieldsQuery, String siteId) {
        Example example = buildExample(empAdditionalFieldsQuery, siteId);
        return empAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<EmpAdditionalFieldsDO> selectByCompanyId(String empId, String companyId, String moduleCode, String siteId) {
        Example example = new Example(EmpAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("empId", empId)
                .andEqualTo("companyId", companyId);
        example.and()
                .andNotEqualTo("type", TYPE_CHECK_IN)
                .orIsNull("type");
        if (moduleCode != null) {
            example.and()
                    .andEqualTo("moduleCode", moduleCode);
        }
        return empAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<EmpAdditionalFieldsDO> selectByCompanyIdEmpIdAndFieldIds(String companyId, String empId, List<Long> fieldIds) {
        if (CollectionUtils.isEmpty(fieldIds)) {
            return new ArrayList<>();
        }
        Example example = new Example(EmpAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andIn("fieldId", fieldIds)
                .andEqualTo("empId", empId)
                .andEqualTo("companyId", companyId);
        return empAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<EmpAdditionalFieldsDO> selectByEmpId(String empId, String siteId) {
        ParamException.isFalse(StrKit.isEmpty(empId), "员工id不能为空");
        Example example = new Example(EmpAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("empId", empId);
        example.and()
                .andEqualTo("type", TYPE_EMP)
                .orIsNull("type");
        return empAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<EmpAdditionalFieldsDO> selectByEmpIds(List<String> empIds, String siteId) {
        ParamException.isFalse(CollectionUtils.isEmpty(empIds), "员工id不能为空");
        Example example = new Example(EmpAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andIn("empId", empIds);
        example.and()
                .andEqualTo("type", TYPE_EMP)
                .orIsNull("type");
        return empAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<EmpAdditionalFieldsDO> selectByCheckInId(String checkInId, String siteId) {
        ParamException.isFalse(StrKit.isEmpty(checkInId), "预登记人员id不能为空");
        Example example = new Example(EmpAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("empId", checkInId)
                .andEqualTo("type", TYPE_CHECK_IN);
        return empAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public void savePreDelete(String empId, String companyId, String moduleCode, List<EmpAdditionalFieldsAddDTO> fieldAddList, TokenUser tokenUser) {

        List<Long> fields = fieldAddList.stream().map(EmpAdditionalFieldsAddDTO::getFieldId).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(fields)) {
            return;
        }

        //先删除之前的数据
        Example example = new Example(EmpAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId())
                .andEqualTo("empId", empId)
                .andEqualTo("companyId", companyId)
                .andEqualTo("moduleCode", moduleCode)
                .andIn("fieldId", fields);
        List<EmpAdditionalFieldsDO> empAdditionalFieldsDOS = empAdditionalFieldsDAO.selectByExample(example);

        //先逻辑删除指定的字段
        deleteByIds(tokenUser, empAdditionalFieldsDOS.stream().map(BaseDO::getId).toArray(Long[]::new));

        //然后批量新增
        List<EmpAdditionalFieldsDO> insertList = fieldAddList.parallelStream()
                .map(empAdditionalFieldsAddDTO -> {
                    EmpAdditionalFieldsDO empAdditionalFieldsDO = empAdditionalFieldsAddDTO.to(EmpAdditionalFieldsDO.class);
                    empAdditionalFieldsDO.preInsert(tokenUser.getUserId());
                    empAdditionalFieldsDO.setSiteId(tokenUser.getSiteId());
                    return empAdditionalFieldsDO;
                }).collect(Collectors.toList());
        empAdditionalFieldsDAO.insertListAndSetId(insertList);

    }


    /**
     * 根据查询参数，构建example
     *
     * @param empAdditionalFieldsQuery 查询参数
     * @param siteId                   所属站点id
     * @return example
     */
    private Example buildExample(EmpAdditionalFieldsQuery empAdditionalFieldsQuery, String siteId) {
        Example example = new Example(EmpAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (empAdditionalFieldsQuery.getModuleCode() != null) {
            example.and().andEqualTo("moduleCode", empAdditionalFieldsQuery.getModuleCode());
        }
        if (empAdditionalFieldsQuery.getFieldId() != null) {
            example.and().andEqualTo("fieldId", empAdditionalFieldsQuery.getFieldId());
        }
        if (empAdditionalFieldsQuery.getCompanyId() != null) {
            example.and().andEqualTo("companyId", empAdditionalFieldsQuery.getCompanyId());
        }
        if (empAdditionalFieldsQuery.getEmpId() != null) {
            example.and().andEqualTo("empId", empAdditionalFieldsQuery.getEmpId());
        }
        // 排序
        ExampleKit.setExampleOrder(example, empAdditionalFieldsQuery.getOrders());
        return example;
    }
}




